package cn.cdeden.knowledge.dubbo;

import cn.cdeden.common.core.utils.MapstructUtils;
import cn.cdeden.common.oss.enumd.OssModuleOperate;
import cn.cdeden.common.oss.enumd.OssModuleType;
import cn.cdeden.common.satoken.utils.LoginHelper;
import cn.cdeden.knowledge.domain.PersonalFilesTree;
import cn.cdeden.knowledge.domain.TreeDownloadFiles;
import cn.cdeden.knowledge.domain.dto.FilesTreeUploadDto;
import cn.cdeden.knowledge.domain.vo.FilesSizeType;
import cn.cdeden.knowledge.service.PersonalFilesTreeService;
import cn.cdeden.resource.api.OssUploadService;
import cn.cdeden.resource.api.RemoteOssEsService;
import cn.cdeden.resource.api.domain.*;
import cn.cdeden.system.api.RemoteUserService;
import cn.cdeden.system.api.domain.vo.RemoteUserVo;
import cn.cdeden.system.api.model.LoginUser;
import com.alibaba.fastjson2.JSONObject;
import com.baomidou.lock.annotation.Lock4j;
import io.undertow.util.BadRequestException;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.apache.dubbo.config.annotation.DubboReference;
import org.apache.dubbo.config.annotation.DubboService;
import org.redisson.api.RedissonClient;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Transactional;

import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @ProjectName : KnowCore01
 * @Package : cn.cdeden.knowledge.dubbo
 * @ClassName : OssUploadPersonalServiceAImpl
 * @Author : Yu.
 * @Description : // 个人上传实现
 * @Date : 2024/12/6 16:06
 * @Version : 1.0
 */
@Slf4j
@Service
@RequiredArgsConstructor
@DubboService(group = "personal" ,version = "1.0.0")
public class OssUploadPersonalServiceAImpl implements OssUploadService {

    private final PersonalFilesTreeService personalFilesTreeService;

    @DubboReference(check = false)
    private final RemoteUserService remoteUserService;

    @DubboReference(check = false)
    private final RemoteOssEsService remoteOssEsService;

    private final RedissonClient redissonClient;

    @Override
    public RemoteFile getFileDataInfo(String moduleId, Long userId, JSONObject info, OssModuleOperate operate) {
        PersonalFilesTree personalFilesTree = personalFilesTreeService.selectById(moduleId);
        RemoteFile remoteFile = new RemoteFile();
        if (StringUtils.isNotBlank(personalFilesTree.getStorageId())) {
            remoteFile.setOssId(Long.valueOf(personalFilesTree.getStorageId()));
        }
        remoteFile.setVersionId(personalFilesTree.getEdition());
        remoteFile.setVersionName(personalFilesTree.getEditionName());
        remoteFile.setFileSize(personalFilesTree.getSize());
        remoteFile.setFileSuffix(personalFilesTree.getSuffix());
        remoteFile.setModuleType(OssModuleType.Personal.getCode());
        remoteFile.setName(personalFilesTree.getRealName());
        remoteFile.setOriginalName(personalFilesTree.getRealName());
        return remoteFile;
    }

    @Override
    public RemoteOssUpload verifyData(RemoteOssUpload info, Long userId) {
        //判断空间
        RemoteUserVo remoteUserVo = remoteUserService.selectUserByUserId(userId);
        Long sum = remoteUserVo.getStorageSum();
        long storageSum = sum != null ? sum : 0L;
        Long use = remoteUserVo.getStorageUse();
        long storageUse = use != null ? use : 0L;
        long l = storageSum - storageUse;
        if (! (l >= info.getFileSize())) {
            throw new RuntimeException("上传文件的大小超过剩余可使用空间");
        }
        //对于同类型文件才判断重名
        //根据parentId查询出上传的文件或者文件夹与当前路径下是否重名，如果重名生成一个新的名称

//        List<PersonalFilesTree> personalFilesTrees = personalFilesTreeService.selectByParentIdAll(info.getParentId());
//        List<String> fileNameList = personalFilesTrees.stream()
//            .filter(v -> v.getDeleteId() == null || ! v.getDeleteId().equals("1"))
//            .map(personalFilesTree -> personalFilesTree.getRealName())
//            .collect(Collectors.toList());
//        if (fileNameList.contains(info.getFileName())) {
//            info.setFileName(info.getFileName() + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
//        }
        //存储的路径
//        PersonalFilesTree personalFilesTree = personalFilesTreeService.selectByParentId(info.getParentId());
        //不提供文件路径
//        String newFilePath = personalFilesTree.getPath() + "/" + info.getFileName();
//        info.setFilePath(newFilePath);
        info.setBrandName(remoteUserVo.getMinioBucket());

        return info;
    }

    @Override
    @Transactional
    @Lock4j(name = "personal:", keys = {"#upload.parentId"}, acquireTimeout = 40000, expire = 40000)
    public RemoteFilesBucketPath upload(RemoteFilesUpload upload, Long userId) {

        LoginUser user = remoteUserService.getUserInfo(userId);
        //判断是否需要创建文件夹
        FilesTreeUploadDto uploadDto = new FilesTreeUploadDto();
        uploadDto.setParentId(upload.getParentId());
        uploadDto.setFilePath(upload.getFilePath());
        String filePath = upload.getFilePath();

        if (StringUtils.isNotBlank(filePath)) {
            //调用创建文件夹的方法
            PersonalFilesTree folderFilePath = personalFilesTreeService.createFolderFilePath(user, uploadDto);
            String parentId = folderFilePath.getParentId();
            upload.setParentId(parentId);
        }


        PersonalFilesTree personalFilesTree = new PersonalFilesTree();

        //判断是否为修改文件信息
        if (! upload.getOperate().equals(OssModuleOperate.Edit_Save)) {
            //获取树的头节点
            PersonalFilesTree personalFilesTree1 = personalFilesTreeService.selectByParentId(upload.getParentId());
            personalFilesTree.setTopParentId(personalFilesTree1.getTopParentId());
            personalFilesTree.setParentId(upload.getParentId());
            if (personalFilesTree1.getType().equals("head")) {
                personalFilesTree.setSuperiorsIds(personalFilesTree1.getTopParentId());
            } else {
                personalFilesTree.setSuperiorsIds(personalFilesTree1.getSuperiorsIds() + "," +upload.getParentId());
            }
            personalFilesTree.setRealName(upload.getFileName());

            //判断文件夹下是否有重名文件
                List<PersonalFilesTree> personalFilesTrees = personalFilesTreeService.selectByParentIdAll(upload.getParentId());
                List<String> realNames = personalFilesTrees
                    .stream()
                    .filter(v -> v.getDeleteId() == null || ! v.getDeleteId().equals("1"))
                    .map(v -> v.getRealName() + "." + v.getSuffix())
                    .collect(Collectors.toList());
                if (realNames.contains(upload.getFileName() + "." +upload.getFileSuffix())) {
                    personalFilesTree.setRealName(personalFilesTree.getRealName() + "_" + new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()));
                }


            personalFilesTree.setSuffix(upload.getFileSuffix());
            personalFilesTree.setSuperiorsPath(personalFilesTree1.getPath());
            personalFilesTree.setType("file");
            personalFilesTree.setStorageId(upload.getStorageId());
            personalFilesTree.setStorageType("minio");
            personalFilesTree.setSize(upload.getFileSize());
            personalFilesTree.setEditionName(upload.getVersionName());
            personalFilesTree.setEdition(upload.getVersionId());
            personalFilesTree.setCreateId(userId.toString());
            personalFilesTree.setCreateBy(user.getUsername());
            personalFilesTree.setCreateTime(new Date());
            personalFilesTree.setUpdateId(userId.toString());
            personalFilesTree.setUpdateBy(user.getUsername());
            personalFilesTree.setUpdateTime(new Date());
            personalFilesTree.setRemarks(upload.getRemarks());
            personalFilesTree.setPath(personalFilesTree1.getPath() + "/" + upload.getFileName());
            personalFilesTreeService.insertOne(personalFilesTree);

            //es中新增数据
            RemoteEsFilesTree remoteEsFilesTree = new RemoteEsFilesTree();
            remoteEsFilesTree.setId(personalFilesTree.getId());
            remoteEsFilesTree.setLibraryType(OssModuleType.Personal.getCode());
            remoteEsFilesTree.setVersionId(personalFilesTree.getEdition());
            remoteEsFilesTree.setVersionName(personalFilesTree.getEditionName());
            remoteEsFilesTree.setSuffix(personalFilesTree.getSuffix());
            remoteEsFilesTree.setType(personalFilesTree.getType());
            remoteEsFilesTree.setStorageId(personalFilesTree.getStorageId());
            remoteEsFilesTree.setSize(personalFilesTree.getSize());
            remoteEsFilesTree.setCreateBy(userId);
            remoteEsFilesTree.setCreateTime(personalFilesTree.getCreateTime());
            remoteEsFilesTree.setUpdateBy(userId);
            remoteEsFilesTree.setUpdateTime(personalFilesTree.getUpdateTime());
            remoteEsFilesTree.setRealName(personalFilesTree.getRealName());
            remoteEsFilesTree.setParentId(personalFilesTree.getParentId());
            remoteEsFilesTree.setUserIdList(Arrays.asList(userId.toString()));
            try {
                String insert = remoteOssEsService.insert(remoteEsFilesTree);
                //修改个人文件中的esId
                PersonalFilesTree personalFilesTreeUpdate = new PersonalFilesTree();
                personalFilesTreeUpdate.setId(personalFilesTree.getId());
                personalFilesTreeUpdate.setEsId(insert);
                personalFilesTreeService.updateById(personalFilesTreeUpdate);
            } catch (Exception e) {
                log.error("es插入数据失败",e);
            }





            //更新上级文件的大小
            personalFilesTreeService.upDateFolderSize(personalFilesTree, FilesSizeType.AddSize);
            return RemoteFilesBucketPath.of(user.getMinioBucket()).setUserList(Arrays.asList(user.getUserId().toString()));
        }
        //查询
        PersonalFilesTree personalFilesTree1 = personalFilesTreeService.selectByParentId(upload.getModuleId());
        //修改文件信息
        personalFilesTree.setId(Long.valueOf(upload.getModuleId()));
        personalFilesTree.setEdition(upload.getVersionId());
        personalFilesTree.setEditionName(upload.getVersionName());
        personalFilesTree.setUpdateId(userId.toString());
        personalFilesTree.setUpdateBy(user.getUsername());
        personalFilesTree.setUpdateTime(new Date());
        personalFilesTree.setSize(upload.getFileSize());
        personalFilesTreeService.updateById(personalFilesTree);

        //修改es中的数据
        try {
            RemoteEsFilesTree remoteEsFilesTree = new RemoteEsFilesTree();
            remoteEsFilesTree.setId(Long.valueOf(upload.getModuleId()));
            remoteEsFilesTree.setLibraryType(OssModuleType.Personal.getCode());
            remoteEsFilesTree.setVersionId(personalFilesTree.getEdition());
            remoteEsFilesTree.setVersionName(personalFilesTree.getEditionName());
            remoteEsFilesTree.setUpdateBy(userId);
            remoteEsFilesTree.setUpdateTime(personalFilesTree.getUpdateTime());
            remoteEsFilesTree.setStorageId(upload.getStorageId());
            remoteEsFilesTree.setEsId(personalFilesTree1.getEsId());
            String update = remoteOssEsService.update(remoteEsFilesTree);
            personalFilesTree.setEsId(update);
            personalFilesTreeService.updateById(personalFilesTree);
        }catch (Exception e){
            log.error("es修改数据失败",e);
        }
        //修改文件夹大小
        personalFilesTreeService.upDateFolderSizeUpDate(personalFilesTree1, personalFilesTree1.getSize() , upload.getFileSize());

        return RemoteFilesBucketPath.of(user.getMinioBucket(), JSONObject.from(personalFilesTree)).setUserList(Arrays.asList(user.getUserId().toString()));

    }

    @Override
    public List<RemoteFilesDownload> downloadFile(List<String> idList, Long userId, JSONObject jsonObject) {

        List<TreeDownloadFiles> treeDownloadFiles = personalFilesTreeService.folderSonFiles(idList, true);
        //封装数据
//        List<PersonalFilesTree> treeDownloadFiles = personalFilesTreeService.selectByIds(idList);
//        List<TreeDownloadFiles> treeDownloadFiles = personalFilesTreeService.folderSonFiles(idList, true);
        //处理数据
        List<RemoteFilesDownload> remoteFilesDownloadList = new ArrayList<>();
        treeDownloadFiles.forEach( v -> {
            remoteFilesDownloadList.add(RemoteFilesDownload.builder()
                .storageId(v.getStorageId())
                .dateId(v.getId().toString())
                .parentId(idList.contains(v.getId().toString()) ? null : v.getParentId())
                .fileSize(v.getSize())
                .fileName(v.getRealName())
                .fileSuffix(v.getSuffix())
                .isFolder(v.getType().equals("folder"))
                .versionId(v.getEdition())
                .versionName(v.getEditionName())
//                .isFolder(v.getLibraryType().equals("folder"))
                .build());
        });
        return remoteFilesDownloadList;
    }
}
